/**
    Copyright (C) 2011  Alexander Vollmer

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.jefb.web.controller;

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.imageio.ImageIO;

import org.jefb.service.IUserSessionService;
import org.jefb.web.model.DirectoryMananagerModel;
import org.jefb.web.util.ZKUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.event.SelectEvent;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zul.Image;
import org.zkoss.zul.Label;
import org.zkoss.zul.ListModelList;
import org.zkoss.zul.Listbox;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.Toolbar;
import org.zkoss.zul.Toolbarbutton;

@org.springframework.stereotype.Component
@Scope("prototype")
public class ImageViewerController extends GenericForwardComposer implements
		Serializable {
	
	private static final long serialVersionUID = 1L;
	//TODOs
	//TODO implement prev and next buttons
	//TODO implement image rotation
	//TODO add scrolling

	// Models
	@Autowired
	private DirectoryMananagerModel directoryManagerModel;
	@Autowired
	private IUserSessionService userSessionService;

	private List<Integer> scaleValues = Arrays.asList(new Integer[] { 25, 50,
			75, 100, 120, 150, 175, 200 });
	private Integer currentScaleIndex = 3;

	
	private File imageFile;
	// UI-components
	private Image currentImage = null;	

	public ImageViewerController() {

	}

	public void init() {

	}

	public void doAfterCompose(Component comp) throws Exception {
		super.doAfterCompose(comp);
		setImageFile(directoryManagerModel.getSelectedFile().getFile());
		createToolbar(comp);
		loadImage(comp);
	}

	private void createToolbar(final Component comp) {
		Toolbar imageToolbar = new Toolbar();
		imageToolbar.setParent(comp);

//		Toolbarbutton prevToolbarbutton = new Toolbarbutton();
//		prevToolbarbutton.setImage("../img/fs22/prev.png");
//		prevToolbarbutton.setParent(imageToolbar);
//
//		Toolbarbutton nextToolbarbutton = new Toolbarbutton();
//		nextToolbarbutton.setImage("../img/fs22/next.png");
//		nextToolbarbutton.setParent(imageToolbar);

		Label scaleLabel = new Label("Scale(%):");
		scaleLabel.setParent(imageToolbar);

		final Listbox scaleListbox = new Listbox();
		scaleListbox.setMold("select");
		final ListModelList scaleListModel = new ListModelList(scaleValues);
		scaleListModel.addSelection(100);
		scaleListbox.setModel(scaleListModel);
		scaleListbox.setParent(imageToolbar);
		
		//zoom in button
		final Toolbarbutton zoomInToolbarbutton = new Toolbarbutton();
		zoomInToolbarbutton.setImage("../img/fs22/viewmag.png");
		zoomInToolbarbutton.setParent(imageToolbar);

		//zoom out button
		final Toolbarbutton zoomOutToolbarbutton = new Toolbarbutton();
		zoomOutToolbarbutton.setImage("../img/fs22/viewmag-.png");
		zoomOutToolbarbutton.setParent(imageToolbar);
		
		//add events to the created components
		
		scaleListbox.addEventListener(Events.ON_SELECT, new EventListener() {
			public void onEvent(Event event) throws Exception {
				if (event instanceof SelectEvent) {
					SelectEvent selectionEvent = (SelectEvent) event;
					Set<?> selectedItems = selectionEvent.getSelectedItems();
					Iterator<?> iterator = selectedItems.iterator();
					if (iterator.hasNext()) {
						Listitem listitem = (Listitem) iterator.next();
						currentScaleIndex = scaleValues.indexOf((Integer) listitem.getValue());
						if(currentScaleIndex==scaleValues.size()-1){
							zoomInToolbarbutton.setDisabled(true);
						}
						if(currentScaleIndex==0){
							zoomOutToolbarbutton.setDisabled(true);
						}
						loadImage(comp);
					}

				}
			}
		});
		
		zoomInToolbarbutton.addEventListener(Events.ON_CLICK, new EventListener() {
			public void onEvent(Event event) throws Exception {
				if(currentScaleIndex<scaleValues.size()-1){
					currentScaleIndex++;
					zoomOutToolbarbutton.setDisabled(false);
					scaleListModel.clearSelection();
					scaleListModel.addSelection(scaleValues.get(currentScaleIndex));
					scaleListbox.setModel(scaleListModel);
				}
				if(currentScaleIndex==scaleValues.size()-1){
					zoomInToolbarbutton.setDisabled(true);
				}
				loadImage(comp);
			}
		});
		
		zoomOutToolbarbutton.addEventListener(Events.ON_CLICK, new EventListener() {
			public void onEvent(Event event) throws Exception {
				if(currentScaleIndex>0){
					currentScaleIndex--;
					zoomInToolbarbutton.setDisabled(false);
					scaleListModel.clearSelection();
					scaleListModel.addSelection(scaleValues.get(currentScaleIndex));
					scaleListbox.setModel(scaleListModel);
				}
				if(currentScaleIndex==0){
					zoomOutToolbarbutton.setDisabled(true);
				}
				loadImage(comp);
			}
		});
	}

	/**
	 * Load image and fit it for given scale.
	 * @param comp
	 */
	private void loadImage(Component comp) {
		BufferedImage bufferedImage;
		try {
			//load image from source
			bufferedImage = ImageIO.read(imageFile);
			//fetch current scale
			Integer scale = scaleValues.get(currentScaleIndex);
			//calculate width and height according to the current scale
			Integer scaledWidth = (bufferedImage.getWidth() * scale) / 100;
			Integer scaledHeight = (bufferedImage.getHeight() * scale) / 100;
			//get scaled image
			java.awt.Image scaledImage = bufferedImage.getScaledInstance(
					scaledWidth, scaledHeight, java.awt.Image.SCALE_SMOOTH);
			//create new container for scaled image
			BufferedImage bi = new BufferedImage(scaledWidth, scaledHeight,
					BufferedImage.TYPE_INT_RGB);
			//draw image into the new container
			Graphics2D graphics = bi.createGraphics();
			graphics.drawImage(scaledImage, 0, 0, scaledWidth,
					scaledHeight, null);

			//create image component if necessary
			if (currentImage == null) {
				currentImage = new Image();
				currentImage.setParent(comp);
			}
			currentImage.setContent(bi);

		} catch (Exception e) {
			ZKUtils.showWarning("Unable to load image."+e.getMessage());
		}

	}

	public void setDirectoryManagerModel(
			DirectoryMananagerModel directoryManagerModel) {
		this.directoryManagerModel = directoryManagerModel;
	}

	public DirectoryMananagerModel getDirectoryManagerModel() {
		return directoryManagerModel;
	}

	public void setUserSession(IUserSessionService userSessionService) {
		this.userSessionService = userSessionService;
	}

	public IUserSessionService getUserSession() {
		return userSessionService;
	}

	public void setImageFile(File imageFile) {
		this.imageFile = imageFile;
	}

	public File getImageFile() {
		return imageFile;
	}

	public void setScaleValues(List<Integer> scaleValues) {
		this.scaleValues = scaleValues;
	}

	public List<Integer> getScaleValues() {
		return scaleValues;
	}

}
